package com.mmall.concurrency.example.lock;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class LockExample6 {

    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();
        Condition condition = reentrantLock.newCondition();

        new Thread(() -> {
            try {
                reentrantLock.lock();
                log.info("wait signal"); // 1
                /**
                 * 调用此方法之后，这个线程就会从AQS的队列里面移除，对应的操作其实是锁的释放，接着它会马上加入到condition的
                 * 等待队列里面
                 */
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("get signal"); // 4
            reentrantLock.unlock();
        }).start();

        new Thread(() -> {
            reentrantLock.lock();
            log.info("get lock"); // 2
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            /**
             * 执行该方法时，condition的等待队列里有我们的线程1的一个节点，于是将它从condition队列取出并加入到AQS的等待队列内
             * 需要注意的此时的线程1并没有被唤醒，它只是被放到了AQS的等待队列中
             */
            condition.signalAll();
            log.info("send signal ~ "); // 3
            // 线程2释放锁之后，AQS的等待队列中只剩线程1，于是按顺序唤醒线程1
            reentrantLock.unlock();
        }).start();
    }
}
